#include "stdafx.h"
#include "charset/textiterator.hpp"
#include "charset/textencode.hpp"
#include <algorithm>
#include "stdlib/bugcheck.hpp"
using namespace JHCPP::stdlib;

namespace JHCPP
{
	namespace charset
	{	
		/////////////////////////////////////////////////////////////////
		//CTextIterator
		/////////////////////////////////////////////////////////////////
		CTextIterator::CTextIterator() : m_pEncode(0)
		{
		}

		CTextIterator::CTextIterator(const std::string& str, const CTextEncode& encode)
		: m_pEncode(&encode),
		m_it(str.begin()),
		m_end(str.end())
		{
		}

		CTextIterator::CTextIterator(const std::string::const_iterator& begin, const std::string::const_iterator& end, const CTextEncode& encode)
		:m_pEncode(&encode),
		m_it(begin),
		m_end(end)
		{
		}

		CTextIterator::CTextIterator(const std::string& str)
		:m_pEncode(0),
		m_it(str.end()),
		m_end(str.end())
		{
		}

		CTextIterator::CTextIterator(const std::string::const_iterator& end)
		:m_pEncode(0),
		m_it(end),
		m_end(end)
		{
		}

		CTextIterator::CTextIterator(const CTextIterator& it):
		m_pEncode(it.m_pEncode),
		m_it(it.m_it),
		m_end(it.m_end)
		{
		}

		CTextIterator::~CTextIterator()
		{
		}

		CTextIterator& CTextIterator::operator = (const CTextIterator& it)
		{
			if (&it != this)
			{
				m_pEncode = it.m_pEncode;
				m_it        = it.m_it;
				m_end       = it.m_end;
			}
			return *this;
		}

		void CTextIterator::swap(CTextIterator& it)
		{
			std::swap(m_pEncode, it.m_pEncode);
			std::swap(m_it, it.m_it);
			std::swap(m_end, it.m_end);
		}

		int CTextIterator::operator * () const
		{
			jh_check_ptr (m_pEncode);
			jh_assert (m_it != m_end);
			std::string::const_iterator it = m_it;

			unsigned char buffer[CTextEncode::MAX_SEQUENCE_LENGTH];
			unsigned char* p = buffer;

			if (it != m_end)
				*p++ = *it++;
			else
				*p++ = 0;

			int read = 1;
			int n = m_pEncode->queryConvert(buffer, 1);

			while (-1 > n && (m_end - it) >= -n - read)
			{
				while (read < -n && it != m_end)
				{ 
					*p++ = *it++; 
					read++; 
				}
				n = m_pEncode->queryConvert(buffer, read);
			}

			if (-1 > n)
			{
				return -1;
			}
			else
			{
				return n;
			}
		}

		CTextIterator& CTextIterator::operator ++ ()
		{
			jh_check_ptr (m_pEncode);
			jh_assert (m_it != m_end);

			unsigned char buffer[CTextEncode::MAX_SEQUENCE_LENGTH];
			unsigned char* p = buffer;

			if (m_it != m_end)
				*p++ = *m_it++;
			else
				*p++ = 0;

			int read = 1;
			int n = m_pEncode->sequenceLength(buffer, 1);

			while (-1 > n && (m_end - m_it) >= -n - read)
			{
				while (read < -n && m_it != m_end)
				{ 
					*p++ = *m_it++; 
					read++; 
				}
				n = m_pEncode->sequenceLength(buffer, read);
			}
			while (read < n && m_it != m_end)
			{ 
				m_it++; 
				read++; 
			}

			return *this;
		}

		CTextIterator CTextIterator::operator ++ (int)
		{
			CTextIterator prev(*this);
			operator ++ ();
			return prev;
		}

		bool CTextIterator::operator == (const CTextIterator& it) const
		{
			return m_it == it.m_it;
		}

		bool CTextIterator::operator != (const CTextIterator& it) const
		{
			return m_it != it.m_it;
		}

		CTextIterator CTextIterator::end() const
		{
			return CTextIterator(m_end);
		}


		/////////////////////////////////////////////////////////////////
		//CTextIterator
		/////////////////////////////////////////////////////////////////
		CTextBufferIterator::CTextBufferIterator() 
		: m_pEncode(0),
		m_it(0),
		m_end(0)
		{
		}

		CTextBufferIterator::CTextBufferIterator(const char* begin, const CTextEncode& encode):
		m_pEncode(&encode),
		m_it(begin),
		m_end(begin + std::strlen(begin))
		{
		}

		CTextBufferIterator::CTextBufferIterator(const char* begin, std::size_t size, const CTextEncode& encode):
		m_pEncode(&encode),
		m_it(begin),
		m_end(begin + size)
		{
		}

		CTextBufferIterator::CTextBufferIterator(const char* begin, const char* end, const CTextEncode& encode):
		m_pEncode(&encode),
		m_it(begin),
		m_end(end)
		{
		}

		CTextBufferIterator::CTextBufferIterator(const char* end):
		m_pEncode(0),
		m_it(end),
		m_end(end)
		{
		}

		CTextBufferIterator::CTextBufferIterator(const CTextBufferIterator& it):
		m_pEncode(it.m_pEncode),
		m_it(it.m_it),
		m_end(it.m_end)
		{
		}

		CTextBufferIterator::~CTextBufferIterator()
		{
		}

		CTextBufferIterator& CTextBufferIterator::operator = (const CTextBufferIterator& it)
		{
			if (&it != this)
			{
				m_pEncode = it.m_pEncode;
				m_it        = it.m_it;
				m_end       = it.m_end;
			}
			return *this;
		}

		void CTextBufferIterator::swap(CTextBufferIterator& it)
		{
			std::swap(m_pEncode, it.m_pEncode);
			std::swap(m_it, it.m_it);
			std::swap(m_end, it.m_end);
		}

		int CTextBufferIterator::operator * () const
		{
			jh_check_ptr (m_pEncode);
			jh_assert (m_it != m_end);
			const char* it = m_it;

			unsigned char buffer[CTextEncode::MAX_SEQUENCE_LENGTH];
			unsigned char* p = buffer;

			if (it != m_end)
				*p++ = *it++;
			else
				*p++ = 0;

			int read = 1;
			int n = m_pEncode->queryConvert(buffer, 1);

			while (-1 > n && (m_end - it) >= -n - read)
			{
				while (read < -n && it != m_end)
				{ 
					*p++ = *it++; 
					read++; 
				}
				n = m_pEncode->queryConvert(buffer, read);
			}

			if (-1 > n)
			{
				return -1;
			}
			else
			{
				return n;
			}
		}

		CTextBufferIterator& CTextBufferIterator::operator ++ ()
		{
			jh_check_ptr (m_pEncode);
			jh_assert (m_it != m_end);

			unsigned char buffer[CTextEncode::MAX_SEQUENCE_LENGTH];
			unsigned char* p = buffer;

			if (m_it != m_end)
				*p++ = *m_it++;
			else
				*p++ = 0;

			int read = 1;
			int n = m_pEncode->sequenceLength(buffer, 1);

			while (-1 > n && (m_end - m_it) >= -n - read)
			{
				while (read < -n && m_it != m_end)
				{ 
					*p++ = *m_it++; 
					read++; 
				}
				n = m_pEncode->sequenceLength(buffer, read);
			}
			while (read < n && m_it != m_end)
			{ 
				m_it++; 
				read++; 
			}

			return *this;
		}

		CTextBufferIterator CTextBufferIterator::operator ++ (int)
		{
			CTextBufferIterator prev(*this);
			operator ++ ();
			return prev;
		}

		bool CTextBufferIterator::operator == (const CTextBufferIterator& it) const
		{
			return m_it == it.m_it;
		}

		bool CTextBufferIterator::operator != (const CTextBufferIterator& it) const
		{
			return m_it != it.m_it;
		}

		CTextBufferIterator CTextBufferIterator::end() const
		{
			return CTextBufferIterator(m_end);
		}

	}//end of namespace charset
}//end of namespace JHCPP
